# Copyright (c) Facebook, Inc. and its affiliates.
#
# Adds generation of build info as library to the project.
# The library name is supplied as argument. After the library is linked with,
# the code can use variables defined in `openr/commom/CMakeBuildInfo.h`.
# This function will generate `GenBuildInfo.txt` file in binaries folder
# and add execution of `cmake -P <binary dir>/GenBuildInfo.txt` during build
# which will produce and compile C++ source code with build info and link it
# into static library.
function(add_build_info LIB_NAME)
  set(cmake_file "${CMAKE_BINARY_DIR}/build_info/GenBuildInfo.txt")
  set(cpp_file "${CMAKE_BINARY_DIR}/build_info/CMakeBuildInfo.cpp")

  file(WRITE ${cmake_file}
    "# Generated by CMake, don't change, changes will be overwritten.\n"
    "set(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR} ${CMAKE_MODULE_PATH})\n"
    "include(FBGenCMakeBuildInfo)\n"
    "generate_build_info(\n"
    "  \"${cpp_file}\"\n"
    "  \"${CMAKE_SOURCE_DIR}\"\n"
    "  \"${CMAKE_BUILD_TYPE}\"\n"
    "  \"${CMAKE_SYSTEM_NAME}\"\n"
    ")"
  )
  add_custom_command(
    OUTPUT
      ${cpp_file}
    MAIN_DEPENDENCY
      ${cmake_file}
    WORKING_DIRECTORY
      ${CMAKE_SOURCE_DIR}
    COMMAND
      "${CMAKE_COMMAND}" -P ${cmake_file}
  )
  add_library(${LIB_NAME} STATIC ${cpp_file})
endfunction()

function(generate_build_info FILE_PATH BUILD_PATH BUILD_MODE BUILD_PLATFORM)
  # Find latest commit hash using git, put it into ${build_rev}
  find_package(Git)
  if(GIT_FOUND)
    execute_process(COMMAND ${GIT_EXECUTABLE} rev-parse --short HEAD
                    WORKING_DIRECTORY ${BUILD_PATH}
                    RESULT_VARIABLE git_rev_parse_rc
                    OUTPUT_VARIABLE build_rev
                    OUTPUT_STRIP_TRAILING_WHITESPACE)
    if(${git_rev_parse_rc} EQUAL 0)
      # Given that rev-parse is successful, get commit timestamp now
      execute_process(COMMAND ${GIT_EXECUTABLE} show -s --format=%ct ${build_rev}
                      WORKING_DIRECTORY ${BUILD_PATH}
                      RESULT_VARIABLE git_show_unixtime_rc
                      OUTPUT_VARIABLE build_rev_unixtime
                      OUTPUT_STRIP_TRAILING_WHITESPACE)
      if(NOT ${git_show_unixtime_rc} EQUAL 0)
        message(WARNING "Git show failed, build will not contain rev date.")
        set(build_rev_unixtime "0")
      endif()
    else()
      message(WARNING
              "Git rev-parse failed, build will not contain git hash.")
      set(build_rev "unknown")
      set(build_rev_unixtime "0")
    endif()
  else()
    set(build_rev "unknown")
    set(build_rev_unixtime "0")
  endif()

  # Find user through OS environment variable $USER
  set(build_user $ENV{USER})
  cmake_host_system_information(RESULT build_hostname QUERY FQDN)
  set(build_tool ${CMAKE_COMMAND})

  # Store current time to variables. We expect that next two commands will
  # happen withing same second.
  string(TIMESTAMP build_datetime UTC)
  string(TIMESTAMP build_unixtime "%s" UTC)

  file(WRITE ${FILE_PATH}
    "// Generated by CMake, don't change, changes will be overwritten.\n"
    "const char* BuildInfo_kUser = \"${build_user}\";\n"
    "const char* BuildInfo_kTime = \"${build_datetime}\";\n"
    "unsigned long long BuildInfo_kTimeUnix = ${build_unixtime};\n"
    "const char* BuildInfo_kHost = \"${build_hostname}\";\n"
    "const char* BuildInfo_kPath = \"${BUILD_PATH}\";\n"
    "const char* BuildInfo_kRevision = \"${build_rev}\";\n"
    "unsigned long long BuildInfo_kRevisionCommitTimeUnix = ${build_rev_unixtime};\n"
    "const char* BuildInfo_kPlatform = \"${BUILD_PLATFORM}\";\n"
    "const char* BuildInfo_kBuildTool = \"${build_tool}\";\n"
    "const char* BuildInfo_kBuildMode = \"${BUILD_MODE}\";\n"
  )
  message("Generated build info: ${FILE_PATH}")
endfunction()
